package com.feicheng.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.feicheng.common.constant.Constant;
import com.feicheng.common.exception.SystemException;
import com.feicheng.common.message.LoginMessage;
import com.feicheng.common.result.ResultInfo;
import com.feicheng.common.wx.WxHTTPInterface;
import com.feicheng.persistence.entity.Account;
import com.feicheng.persistence.entity.ClientDeposit;
import com.feicheng.persistence.entity.DepositBackRequest;
import com.feicheng.persistence.entity.DepositRecord;
import com.feicheng.persistence.entity.DepositTransferBatch;
import com.feicheng.persistence.entity.DepositTransferDetail;
import com.feicheng.persistence.entity.PaymentRecord;
import com.feicheng.persistence.entity.User;
import com.feicheng.persistence.mapper.DepositBackRequestMapper;
import com.feicheng.persistence.mapper.DepositTransferBatchMapper;
import com.feicheng.persistence.model.DepositBackRequestStoreClient;
import com.feicheng.persistence.service.IAccountService;
import com.feicheng.persistence.service.IClientDepositService;
import com.feicheng.persistence.service.IDepositBackRequestService;
import com.feicheng.persistence.service.IDepositRecordService;
import com.feicheng.persistence.service.IDepositTransferBatchService;
import com.feicheng.persistence.service.IDepositTransferDetailService;
import com.feicheng.persistence.service.IPaymentRecordService;
import com.feicheng.service.BaseService;
import com.feicheng.service.IFPayBackService;
import com.feicheng.wxpay.app.WxAppPayBean;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.Status;

@Service
public class FPayBackServiceImpl extends BaseService implements IFPayBackService {

	@Autowired
	IDepositTransferBatchService depositTransferBatchService;

	@Autowired
	IDepositBackRequestService depositBackRequestService;

	@Autowired
	DepositBackRequestMapper depositBackRequestMapper;

	@Autowired
	IDepositTransferDetailService depositTransferDetailService;

	@Autowired
	DepositTransferBatchMapper depositTransferBatchMapper;

	@Autowired
	LoginMessage loginMessage;

	@Autowired
	IDepositBackRequestService iDepositBackRequestService;

	@Autowired
	IDepositTransferBatchService iDepositTransferBatchService;

	@Autowired
	IDepositTransferDetailService iDepositTransferDetailService;
	
	@Autowired
	IDepositRecordService iDepositRecordService;
	
	@Autowired
	IPaymentRecordService iPaymentRecordService;
	
	@Autowired
	IAccountService iAccountService;
	
	@Autowired
	IClientDepositService iClientDepositService;
	
	@Resource(name = "wx-http")
    WxHTTPInterface wxHTTPInterface;
	
	@Resource(name = "store-wx-pay")
    Map<String, WxAppPayBean> storeWxPayService;
	
	@Override
	@Transactional
	public synchronized ResultInfo finishDepositRecord(JSONObject param) {
		Integer backId = param.getInteger(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID);
		DepositBackRequest depositBackRequest = this.iDepositBackRequestService.getById(backId);

		QueryWrapper<ClientDeposit> cdQw = new QueryWrapper<ClientDeposit>();
		cdQw.eq("deposit_id", depositBackRequest.getDepositId());
		ClientDeposit clientDeposit = this.iClientDepositService.getOne(cdQw);

		QueryWrapper<Account> acQw = new QueryWrapper<Account>();
		acQw.eq("client_id", clientDeposit.getClientId());
		Account account = this.iAccountService.getOne(acQw);
		
        depositBackRequest.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.BCK);
        depositBackRequest.setUt(LocalDateTime.now());
        User currentUser = super.currentUser();
        depositBackRequest.setUu(currentUser.getUserId());
        depositBackRequestService.updateById(depositBackRequest);
        
        clientDeposit.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.BCK);
        this.iClientDepositService.update(clientDeposit, cdQw);
        
        account.setDepositAmount(0);
        this.iAccountService.updateById(account);
        
        return ResultInfo.success();
	}
	
	@Override
	@Transactional
	public synchronized ResultInfo rejectDepositRecord(JSONObject param) {
		Integer backId = param.getInteger(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID);
		String reason = param.getString(Constant.ENTITY.DEPOSIT_BACK_REQUEST.REASON);
		DepositBackRequest depositBackRequest = this.iDepositBackRequestService.getById(backId);
		
		
        depositBackRequest.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.REJ);
        depositBackRequest.setUt(LocalDateTime.now());
        User currentUser = super.currentUser();
        depositBackRequest.setUu(currentUser.getUserId());
        depositBackRequest.setReason(reason);

        depositBackRequestService.updateById(depositBackRequest);

        return ResultInfo.success();
	}
	
	
	@Override
	@Transactional
	public synchronized ResultInfo agreeDepositRecord(JSONObject param) {
		
		Integer backId = param.getInteger(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID);
		
		DepositBackRequest depositBackRequest = this.iDepositBackRequestService.getById(backId);
		
		DepositRecord depositRecord = iDepositRecordService.getById(depositBackRequest.getDepositId());
		PaymentRecord paymentRecord = iPaymentRecordService.getById(depositRecord.getPayId());
		
		QueryWrapper<ClientDeposit> clientDepositQueryWrapper = new QueryWrapper<ClientDeposit>();
		clientDepositQueryWrapper.eq("deposit_id", depositRecord.getDepositId());
		ClientDeposit clientDeposit = iClientDepositService.getOne(clientDepositQueryWrapper);
		
		QueryWrapper<Account> accountQueryWrapper = new QueryWrapper<Account>();
		accountQueryWrapper.eq("client_id", clientDeposit.getClientId());
		Account account = iAccountService.getOne(accountQueryWrapper);
		
		WxAppPayBean wxPayBean = storeWxPayService.get(String.valueOf(depositRecord.getStoreId()));
		
		CreateRequest request = new CreateRequest();
		
		request.setOutTradeNo(paymentRecord.getOriginalCode());
		request.setOutRefundNo(depositBackRequest.getBackId()+"REF"+depositRecord.getDepositId());
		request.setNotifyUrl(wxHTTPInterface.getNoticeRefund() + depositRecord.getStoreId());
		AmountReq amountReq = new AmountReq();
		amountReq.setRefund(Long.valueOf(account.getDepositAmount()));
		amountReq.setTotal(Long.valueOf(depositRecord.getAmount()));
		amountReq.setCurrency("CNY");
		
		request.setAmount(amountReq);
		
		Refund refundResult = wxPayBean.refund(request);
		
		if (Status.SUCCESS.equals(refundResult.getStatus())) {
			clientDeposit.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.BCK);
			depositBackRequest.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.BCK);
			iDepositBackRequestService.updateById(depositBackRequest);
		} else if (Status.CLOSED.equals(refundResult.getStatus())) {
			clientDeposit.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.CLO);
		} else if (Status.PROCESSING.equals(refundResult.getStatus())) {
			clientDeposit.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.RUN);
		} else {
			clientDeposit.setStatu(Constant.VAL.BACK_REQUEST_DEPOSIT.EXC);
		}
		
		iClientDepositService.update(clientDeposit, clientDepositQueryWrapper);
		
		return ResultInfo.success();
	}

	@Override
	public ResultInfo updateRequestStatu(DepositBackRequest depositBackRequest) {
		// TODO Auto-generated method stub
		if (null == depositBackRequest.getBackId()) {
			// TODO 退款请求ID缺失
			throw new SystemException("退款请求ID缺失");
		}
		// 存入当前修改时间
		depositBackRequest.setUt(LocalDateTime.now());
		QueryWrapper<DepositBackRequest> queryWrapper = new QueryWrapper<DepositBackRequest>();
		queryWrapper.eq(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID, depositBackRequest.getBackId());
		depositBackRequestService.update(depositBackRequest, queryWrapper);
		return ResultInfo.success();
	}

	@Override
	public ResultInfo getDepositTransferDetail(Integer id) {
		// 非空判断
		if (null == id) {
			throw new SystemException("退款批次id不能为空");
		}
		// 构造查询条件
		QueryWrapper<DepositTransferBatch> queryWrapper = new QueryWrapper<DepositTransferBatch>();
		queryWrapper.eq(Constant.ENTITY.DEPOSIT_TRANSFER_BATCH.ID, id);
		QueryWrapper<DepositTransferDetail> wrapper = new QueryWrapper<DepositTransferDetail>();
		wrapper.eq(Constant.ENTITY.DEPOSIT_TRANSFER_DETAIL.D_T_B_ID, id);
		List<DepositTransferBatch> result = iDepositTransferBatchService.list(queryWrapper);
		result.get(0).setDepositTransferDetails(iDepositTransferDetailService.list(wrapper));
		return ResultInfo.success(result);
	}

	@Override
	public ResultInfo payBackAll(Integer storeId) {
		// TODO Auto-generated method stub
		// 条件构造通过store_id查询
		QueryWrapper<DepositBackRequest> wrapper = new QueryWrapper<DepositBackRequest>();
		if (null != storeId) {
			wrapper.eq(Constant.ENTITY.DEPOSIT_BACK_REQUEST.STORE_ID, storeId);
		}

		return ResultInfo.success(iDepositBackRequestService.list(wrapper));
	}

	@Override
	public Page<DepositTransferBatch> page(Integer current, Integer size, Integer clientId) {
		// TODO Auto-generated method stub
		if (clientId == null) {
			throw new SystemException(loginMessage.getE04());
		}

		QueryWrapper<DepositTransferBatch> wrapper = new QueryWrapper<DepositTransferBatch>();
		wrapper.eq("client_id", clientId);
		Page<DepositTransferBatch> p = new Page<DepositTransferBatch>();
		p.setCurrent(current);
		p.setSize(size);

//			p.setRecords(depositTransferBatchMapper.getDepositTransferBatchsPage(p, wrapper));
//			p.setTotal(depositTransferBatchMapper.getDepositTransferBatchsPage(p, wrapper).size());
		return p;

	}

	@Override
	@Transactional
	public ResultInfo depositTransferBatchPost(DepositTransferBatch depositTransferBatch) {

		// 非空验证
		if (!StringUtils.hasLength(depositTransferBatch.getAppid())) {
			throw new SystemException("商户号不能为空");
		}
		if (!StringUtils.hasLength(depositTransferBatch.getOutBatchNo())) {
			throw new SystemException("批次号不能为空");
		}
		if (!StringUtils.hasLength(depositTransferBatch.getBatchName())) {
			throw new SystemException("转账名称不能为空");
		}
		if (!StringUtils.hasLength(depositTransferBatch.getBatchRemark())) {
			throw new SystemException("转账说明不能为空");
		}
		if (depositTransferBatch.getDepositTransferDetails().size() < 1) {
			throw new SystemException("缺少转账关键信息");
		}
		// 存入当前时间
		depositTransferBatch.setCt(LocalDateTime.now());
		// 存入当前状态
		depositTransferBatch.setStatu("申请中");
		// 执行存入数据库
		depositTransferBatchService.save(depositTransferBatch);

		// 创建构造条件
		QueryWrapper<DepositTransferBatch> deQueryWrapper = new QueryWrapper<DepositTransferBatch>();
		deQueryWrapper.eq("out_batch_no", depositTransferBatch.getOutBatchNo());
		List<DepositTransferBatch> deList = depositTransferBatchService.list(deQueryWrapper);

		// 查询所有符合要求的back_id
		// 取出所有的openId；
		List<String> openIds = new ArrayList<String>();
		for (int i = 0; i < depositTransferBatch.getDepositTransferDetails().size(); i++) {
			openIds.add(depositTransferBatch.getDepositTransferDetails().get(i).getOpenid());
		}
		List<Integer> ids = new ArrayList<Integer>();
		// 取出查询结果
		List<DepositBackRequestStoreClient> depositBackRequests = depositBackRequestMapper
				.getDepositBackRequests(openIds);
		// 通过openId的比较 获取对应的back_id;
//		for (int i = 0; i < depositTransferBatch.getDepositTransferDetails().size(); i++) {
//			depositTransferBatch.getDepositTransferDetails().get(i).setDTBId(deList.get(0).getId());
//			for (int j = 0; j < depositBackRequests.size(); j++) {
//				if (depositTransferBatch.getDepositTransferDetails().get(i).getOpenid().equals(depositBackRequests.get(j).getOpenId())) {
//					//将back_id存入对象
//					depositTransferBatch.getDepositTransferDetails().get(i).setBackId(depositBackRequests.get(j).getBackId());
//					//将back_id存入数组
//					ids.add(depositBackRequests.get(j).getBackId());
//				}
//			}
//		}
		// 批量存入
		depositTransferDetailService.saveBatch(depositTransferBatch.getDepositTransferDetails());

		// 批量修改depositBackRequest表状态
		List<DepositBackRequest> desBackRequests = new ArrayList<DepositBackRequest>();
		for (int i = 0; i < ids.size(); i++) {
			DepositBackRequest desBackRequest = new DepositBackRequest();
			desBackRequest.setBackId(ids.get(i));
			desBackRequest.setStatu("RUN");
			desBackRequests.add(desBackRequest);
		}
		depositBackRequestService.saveOrUpdateBatch(desBackRequests);
		return ResultInfo.success();
	}

	@Override

	 @Transactional
	 public ResultInfo depositBackRequest(DepositBackRequest depositBackRequest) {
	
	  
	  //非空验证
	 if(!StringUtils.hasLength(depositBackRequest.getReason())) {
	  throw new SystemException("退款原因不能为空");
	 }
	 if(null == depositBackRequest.getAmount()) {
	  throw new SystemException("金额不能为空");
	 }
	 if(!StringUtils.hasLength(depositBackRequest.getStatu())) {
	  throw new SystemException("退款状态不能为空");
	 }
	 if(null == depositBackRequest.getClientId()) {
	  throw new SystemException("客户id不能为空");
	 }
	 if(null== depositBackRequest.getStoreId()) {
	  throw new SystemException("店铺id不能为空");
	 }
	 depositBackRequest.setCt(LocalDateTime.now());
	 depositBackRequest.setUt(LocalDateTime.now());
	 
	  return ResultInfo.success(depositBackRequestService.save(depositBackRequest));
	 }



	@Override
	public ResultInfo page(Integer current, Integer size, DepositBackRequest depositBackRequest) {
		QueryWrapper<DepositBackRequest>queryWrapper = new QueryWrapper<DepositBackRequest>();
		Page<DepositBackRequest> page = new Page<DepositBackRequest>();
		if(null!=depositBackRequest.getClientId()) {
			queryWrapper.like(Constant.ENTITY.DEPOSIT_BACK_REQUEST.CLIENT_ID,depositBackRequest.getClientId());
		}
		if(null!=depositBackRequest.getStatu()) {
			queryWrapper.like(Constant.ENTITY.DEPOSIT_BACK_REQUEST.STATU,depositBackRequest.getStatu());
		}
		if(null!=depositBackRequest.getStoreId()) {
			queryWrapper.like(Constant.ENTITY.DEPOSIT_BACK_REQUEST.STORE_ID,depositBackRequest.getStoreId());
		}
		if(null!=depositBackRequest.getBackId()) {
			queryWrapper.like(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID,depositBackRequest.getBackId());
		}
		return  ResultInfo.success(depositBackRequestService.page(page,queryWrapper));
	}

	

	@Override
	public ResultInfo putDepositBackRequest(List<DepositBackRequest> depositBackRequest) {
		for (int i = 0; i < depositBackRequest.size(); i++) {
			depositBackRequest.get(i).setUt(LocalDateTime.now());
			
		}
		 
		return ResultInfo.success(depositBackRequestService.updateBatchById(depositBackRequest));
	}

	@Override
	public ResultInfo deDepositBackRequest(Integer backId) {
		if(null==backId) {
			throw new SystemException("退款id不能为空");
		}
		QueryWrapper<DepositBackRequest>queryWrapper = new QueryWrapper<DepositBackRequest>();
		queryWrapper.eq(Constant.ENTITY.DEPOSIT_BACK_REQUEST.BACK_ID, backId);
		return ResultInfo.success(depositBackRequestService.remove(queryWrapper));
	}

	


}

